package consul

import (
	"common/config"
	"fmt"
	"github.com/hashicorp/consul/api"
	uuid "github.com/satori/go.uuid"
	"go.uber.org/zap"
)

/*
*
consul注册grpc服务地址到consul注册中心
*/
type ConsulRegistry struct {
	Host string
	Port int
}

type ConsulRegistryClient interface {
	Register(conf config.ConsulConf, ip string, port int) (string, error)
	UnRegister(serviceId string) (string, error)
}

func NewConsulRegistryClient(conf config.ConsulConf) ConsulRegistryClient {
	return &ConsulRegistry{
		Host: conf.Host,
		Port: conf.Port,
	}
}

/*
*
 */
func (c *ConsulRegistry) Register(conf config.ConsulConf, ip string, port int) (string, error) {
	serviceId := fmt.Sprintf("%s", uuid.NewV4())
	cfg := api.DefaultConfig()
	cfg.Address = fmt.Sprintf("%s:%d", c.Host, c.Port)
	//生成consul client
	client, err := api.NewClient(cfg)
	if err != nil {
		zap.S().Errorf("init consul api newClient err:%v", err)
		return serviceId, err
	}
	//生成健康检查对象
	check := &api.AgentServiceCheck{
		GRPC:                           fmt.Sprintf("%s:%d", ip, port), //这一个接口时自定义的健康检查的接口
		Timeout:                        "5s",
		Interval:                       "5s",
		DeregisterCriticalServiceAfter: "10s",
	}
	//生成注册对象
	registration := new(api.AgentServiceRegistration)
	registration.Check = check
	registration.ID = serviceId
	registration.Name = conf.Register.Name
	registration.Tags = conf.Register.Tags
	registration.Port = port
	registration.Address = ip
	//进行注册操作
	if err = client.Agent().ServiceRegister(registration); err != nil {
		zap.S().Errorf("consulClient serviceRegister error:%v", err)
		return serviceId, err
	}
	return serviceId, nil
}

func (c *ConsulRegistry) UnRegister(serviceId string) (string, error) {
	cfg := api.DefaultConfig()
	cfg.Address = fmt.Sprintf("%s:%d", c.Host, c.Port)
	client, err := api.NewClient(cfg)
	if err != nil {
		zap.S().Errorf("init consul apiNewClient err:%v", err)
		return serviceId, err
	}
	if err = client.Agent().ServiceDeregister(serviceId); err != nil {
		zap.S().Errorf("consulClient serviceDeregister err:%v", err)
		return serviceId, err
	}
	return serviceId, nil
}
